<?php
require_once 'lib/arc2/ARC2.php';
require_once 'item.php';
require_once 'lib/converthelper.php';
require_once('lib/converters/Triples.class.php');
require_once('lib/moriarty/httprequestfactory.class.php');
define('HTTP_400', "HTTP/1.0 400 Bad Request");

class Convert extends Item
{
	var $inputType;
	var $outputType;
	var $accept_mimetypes = array('text/html');
	var $crawled_urls = array();
	var $Resources = false;
	
	function __construct($params)
	{
		if(isset($_GET['output'])) $this->accept_mimetypes[]=$_GET['output'];
		
		if(!empty($_SERVER['HTTP_ACCEPT']))
		{
			$this->accept_mimetypes =  ConvertHelper::accept_header_to_list($_SERVER['HTTP_ACCEPT']);
		}	
 		
	
		parent::__construct($params);
	}
	
	
	function POST()
	{
		if(isset($_POST['resources']))
		{
			$postData = $_POST;
			$postData['prefixes'] = $this->namespaces;
			$Resources = $this->Convert->FormArray->to_resources($postData);
			$xml = $Resources->to_rdfxml();
			$data = $Resources->value();
			$outputType = $this->getOutputType();
		}
		elseif(isset($_POST['data']) AND $_POST['data']['format']=='turtle')
		{
			$outputType = $this->getOutputType();
			
			$parser = ARC2::getTurtleParser();
			$parser->parse($this->location, stripslashes($_POST['data']['content']));
			$this->messages[]='Parsing as Turtle';
			$triples = $parser->getTriples();
			$this->errors = array_merge($this->errors, $parser->getErrors());
			$Triples = new Triples($triples, $this->Convert);
			$Resources = $Triples->to_resources();
			list($xml, $data) = array($Resources->to_rdfxml(), $Resources->value());					
		}
		// ChangeSets
		
		if(isset($_POST['action']) ){
			if( $_POST['action'] == 'changeset')
			{
				// require_once('lib/moriarty/changeset.class.php');
				// require_once('lib/moriarty/changesetbatch.class.php');

				$this->setOutputType('rdf');
				$before_rdf = (!empty($_GET['data-uri']))? $this->GET() : '';
				$cs_args = array(
					 "before"=>  $before_rdf,
					 "after"=>  $xml,
					 "createdDate"=>  date("Y-m-d i:s"),
					 "creatorName"=>  'Talis Semantic Converter',
					 "changeReason"=>  'Edit form was POSTed',
					);
	
				$ChangsetBatch = ARC2::getComponent('Talis_ChangesetBuilderPlugin', $cs_args);
				$Resources = new GraphIndex($ChangsetBatch->__index);
				$xml = $Resources->to_rdfxml();
				$data = $Resources->value();
			}
			else if($_POST['action']=='reify')
			{
				$Resources = $Resources->reify();
				list($xml, $data) = array($Resources->to_rdfxml(), $Resources->value());					
				
			}
			else if($_POST['action']=='dereify')
			{
				$Resources = $Resources->dereify();
				list($xml, $data) = array($Resources->to_rdfxml(), $Resources->value());					
			}
			
		}
		
		if(isset($Resources) AND stristr($outputType, 'exhibit'))
		{
			$data = $Resources->to_exhibit()->value();
		}	
		
		if($ext = ConvertHelper::get_filename_extension('rdf-xml', $outputType, $this->accept_mimetypes))
		{
			$this->filename_extension = $ext;
		}
		else
		{
			$this->errors[]='This Conversion isn\'t  possible (at least not yet)';
			$this->filename_extension = 'html';
		}
		
	
		$this->setOutputType($outputType);
		
		if(isset($_POST['forward']) AND $uri = ($_POST['forward']['uri']))
		{
			$auth = array(
				'username' => $_POST['forward']['user'],
				'password' => $_POST['forward']['password'],
				);
			if(isset($_POST['forward']['method']) AND in_array($_POST['forward']['method'], array('POST','PUT')))
			{
				$method = $_POST['forward']['method'];
			}
			else
			{
				$method = 'POST';
			}
			
			$request_factory = new HttpRequestFactory();
		    $request = $request_factory->make( 'POST', $uri);
		    $request->set_content_type($this->getOutputMimeType());
			$this->set_variables(compact('data','Resources','xml', 'response'));
			ob_start();
			$body = $this->show();
			$body .= ob_get_clean();
			file_put_contents('lastpost.rdf', $body);
		    $request->set_body( $body );
			if(!empty($auth) && !empty($auth['username']) && !empty($auth['password']))
			{
				$request->set_auth($auth['username'].':'.$auth['password']);
			}
			$request->headers["User-Agent"] = 'Talis Converter Service :: Editor';
			$response =  $request->execute();
			$this->setOutputType('text/html');
			$this->filename_extension = 'html';
		}
		
		
		$this->set_variables(compact('data','Resources','xml', 'response'));
		return $this->show();
	}
	
	
	function GET()
	{
		if(isset($_GET['uri']) AND !isset($_GET['data-uri'])) $_GET['data-uri'] = $_GET['uri'];
		if(isset($_GET['data-uri']))
		{

			if(is_array($_GET['data-uri']) ){
				
				if(
					count($_GET['data-uri']) > 1 AND 
				( !empty($_GET['input']) AND 
				!in_array($_GET['input'], array('rdf-xml', 'rdf-json', 'rdf-turtle', 'rdf-html'))
					)
				){
					$this->headers[]=HTTP_400;
					$this->messages[]='Only data from RDF and HTML documents can be merged';
					return $this->show();
				}
				
				foreach($_GET['data-uri'] as $url){
					$this->getDataFromURL($url);
				}
			} else {
				$url = $_GET['data-uri'];
				$this->getDataFromURL($url);
			}
			
			if(empty($this->variables['data'])){
				 $this->errors[]='No triples found';
			}
			

		} //endIF GET['uri']
		
		if($this->filename_extension){
					require 'config/mimetypes.php';
					$mtype = $mimetypes[$this->filename_extension];
					$this->headers[]="Content-type: {$mtype}; charset=utf-8";			
		}
				
		
		return $this->show();	
	}
	
	private function valid_url($url)
	{
		$url = trim($url);
		$invalid_chars = array("\n","\r","\t");
		
		if(strpos($url,'http://')!==0) return false;
		
		foreach($invalid_chars as $char)if(strpos($url,$char) !== false ) return false;
		
		return str_replace(' ', '%20', $url);
	}
	
	function set_variables($arr)
	{
		foreach($arr as $k => $v) $this->variables[$k] = $v ;
	}

	function setOutputType($type)
	{
		$this->outputType = $type;
	}
	
	function getOutputType()
	{
		if(!empty($this->outputType)) return $this->outputType;
		else if( 
			(isset($_POST['output']) AND $outputType = $_POST['output'] )
			OR  
			( isset($_GET['output']) AND $outputType = $_GET['output'] ) 
			//AND !empty($outputType) 
			)
		{
			return trim($outputType);
		}
		else
		{
			 
			return false;
		}
	}
	
	function getOutputMimeType()
	{
		if(isset($_POST['action']) AND $_POST['action']=='changeset') return 'application/vnd.talis.changeset+xml';
		require 'config/mimetypes.php'; //imports configured mimetypes
		$extension = $this->getOutputType();
		return ($m = $mimetypes[$extension])? $m : 'text/plain';
	}
	

	function getDataFromURL($url)
	{
		$url = $this->valid_url($url);

		if($url)
		{
		       $request_factory = new HttpRequestFactory();

			while(!isset($request) OR 
			(isset($response->headers['location']) AND $response->status_code != '200') AND
			(count($this->crawled_urls) < 10 OR in_array($url, $this->crawled_urls))
			)
			{

				$this->crawled_urls[]=$url;

				if(isset($response->headers['location']))
				{
					 $url = $response->headers['location'];
				}

			  $request = $request_factory->make( 'GET', $url );
		   	  $request->set_accept("text/n3, application/turtle, application/rdf+xml, application/xml, application/xhtml+xml;q=0.6, text/html;q=0.5, text/xml, text/plain, */*;q=0.2");
			 
				$request->headers["User-Agent"] = 'Morph Converter Service (http://morph.talis.com/)';
			//$request->set_content_type("application/x-www-form-urlencoded");					
			    $response = $request->execute();
			}

			if($response->status_code!='200')
			{
				$error = 'A Document could not be retrieved from '.$url.' '.$response->to_html();
				$this->errors[]= $error;
				header("HTTP/1.x 502 Bad Gateway");
				return $this->show();
			}

			foreach($response->headers as $k => $v ){
				if(in_array($k, array('cache-control','etag','location'))){ 
					$this->headers[]= "$k: $v";
				}
			}

			$inputType =!empty($_GET['input'])? trim($_GET['input']) : ConvertHelper::choose_input($url, $response);

			$document = trim($response->body);



			switch($inputType){

				case 'sparql-xml':
					list($xml, $data) = array($document, $this->Convert->SPARQL_XML->to_array($document)->value());
					$sparql_results = $data;
					break;
				case 'facet-xml':
					list($xml, $data) = array($document, $this->Convert->FacetXML->to_array($document)->value());
					break;
				case 'rdf-xml':
					$parser = ARC2::getRDFXMLParser();
					$parser->parse($url, $document);
					$data = $parser->getSimpleIndex(0);
					$this->importToIndex($data);
					$this->messages[]='Parsing '.$url.' as RDF/XML';
					break;
				case 'rdf-html':
					$parser = ARC2::getSemHTMLParser();
					$parser->parse($url, $document);
					$parser->extractRDF("erdf rdfa dc openid hcard-foaf xfn rel-tag-skos");
					$this->messages[]='Parsing '.$url.' as Semantic HTML';
					$data = $parser->getSimpleIndex(0);
					$this->importToIndex($data);
					break;
				case 'rdf-turtle':
					$parser = ARC2::getTurtleParser();
					$parser->parse($url, $document);
					$this->messages[]='Parsing as Turtle';
					$data = $parser->getSimpleIndex(0);
					$this->importToIndex($data);
					break;
				case 'rdf-json':
					$data = json_decode($document, true);
					if(GraphIndex::is_valid($data))
					{
	   					 $this->messages[]='Parsing '.$url.' as RDF/JSON';
						$this->importToIndex($data);
						 break;
					}
					else
					{
						$this->errors[]='Document at '.$url.' is not valid RDF/JSON';
					}
				case 'invalid-json':
				 	$this->headers[]=HTTP_400;
					$this->errors[]=$url." is invalid JSON, and cannot be converted, sorry.";
					break;
					
				default:
					if(!empty($_GET['input'])){
						$this->messages[]="Unrecognised input format <q>".htmlentities($_GET['input'])."</q> from ".$url." - trying to parse as RDF";
						$this->headers[]=HTTP_400;
						
					} else {
						$this->messages[]="Not sure what format ".$url." is - trying to parse as RDF";
					}

					$inputType = 'rdf';
					$parser = ARC2::getRDFParser();
					$parser->parse($url, $document);
					$data = $parser->getSimpleIndex(0);
					$this->importToIndex($data);
					break;

			}

			$outputType = $this->getOutputType();


			if(!empty($this->Resources))
			{
				if( isset($parser)  AND isset($parser->nsp))
				{
					$count = 0;
					foreach($parser->nsp as $k => $v){
						if(!$v){
							$parser->nsp[$k] = 'n'.$count++;
						}
					}
					$parser_ns = ($n = $parser->nsp AND !empty($n))? array_flip($n) : array();
					foreach($parser_ns as $k => $v){
						unset($parser_ns[$k]);
					}
					$r_ns = $this->Resources->namespaces;
					$this->namespaces = array_merge($r_ns,$parser_ns, $this->namespaces);
				}

				$this->variables['namespaces'] = $this->namespaces;
				$Resources = $this->Resources;
				$xml = $Resources->to_rdfxml();
				$data = $Resources->value();		
			} 
			


			if(stristr($outputType, 'exhibit'))
			{
				$data = $this->Resources->to_exhibit()->value();	
			} 			
			
			$this->set_variables(compact('xml','data', 'sparql_results', 'Resources', '$url'));				

			if($ext = ConvertHelper::get_filename_extension($inputType, $outputType, $this->accept_mimetypes))
			{
				$this->filename_extension = $ext;
			}
			else
			{
				if($outputType)
				{
					$this->headers[]= HTTP_400;
					$this->errors[]='This Conversion isn\'t  possible (at least not yet)';
				}
				
				$this->filename_extension = 'html';
			}

		} //endif url is valid
		else
		{
			$this->headers[]=HTTP_400;
			$this->errors[]='The URL you entered is invalid, please make sure it begins with http://';
		}		
	}

	function importToIndex($data){
		if(!empty($data)){
			if(!$this->Resources)
			{
				$this->Resources = new GraphIndex($data);
			} 
			else 
			{
				$this->Resources->import($data);
			}
		
			list($xml, $data) = array($this->Resources->to_rdfxml(), $this->Resources->value());	
		

			$this->variables['rdf_xml'] = $xml;
			$this->variables['xml'] = $xml;
			$this->variables['data'] = $data;
			$this->variables['resources'] = $data;
		}
	}


}


?>